# To change this template, choose Tools | Templates
# and open the template in the editor.
from direct.gui.DirectGui import *
from direct.gui.OnscreenText import OnscreenText
from direct.task import Task
from pandac.PandaModules import *
import random

lightList = [] #Stores the lighting of the game
TubesOnGame = []	#List of tubes in game.
NextTubes = []	  #List of the next tubes that can follow another one.
FirstTubePos = 45  #Position of the first tube on screen.
PositionListZ = []   #List of Z positions.
PositionListX = []   #List of X positions.
ChosenTube = ""	 #The tube chosen by the user, it will be the next one to be drawn.
buttonObjectList = [] #List of buttons loaded on the screen
buttonObject = ""
scalePipe = [0.1, 0.1, 0.1] #Scale of the pipes
scaleGiantTube = [1.2, 1, 5] #Scale of the giant tube rounding the scene
CameraPosition = 20 #Initial Z Camera position
LastTube = "" #LastTube loaded on the screen
GiantTube = "" #Store the GiantTube and the back wall
points = "0" #Player points value
pointText = "" #A text on the screen, representing the player points
sphere = ""  #Store the sphere model
isItOver = 0 #1 if the game is over, 0 if the game continues
changes = 3 #Number of times the player can use the button CHANGE
buttonChange = ""
randomPower = 0  #Used to randomly choose special power in certain tubes.
tubeNameSpecial = ""
gravity = [-2.00] #The value of the gravity in the game
music = "" 
pipeObjectsList = [] #Stores the pipe objects
gameOverTexts = []  #The texts used when the player fails

#Buttons and objects used on the initial menu
userName = "" #Stores the player that is playing the game.
frame = ""
userNameObjectLabel = ""
scoreScreenList = []
helpTextList = []
difficultButtons = []
mainButtons = []

#Physics objects
gravityFN = ""
gravityFNP = ""
gravityForce = ""
PhysicsObject = "" #Stores the sphere used on the physics.

class objects:
	def __init__(self):
		return None

	#Function that loads a pipe (just prototype to test)
	def loadPipe(self, namepath, x, y, z):
		global pipeObjectssList
		
		pipe = loader.loadModel(namepath)
		# Reparent the model to render.
		pipe.reparentTo(render)
		self.setObjectScale(pipe, scalePipe[0], scalePipe[1], scalePipe[2])
		self.setObjectPosition(pipe, x, y, z)
		#Enables transparency and defines color of the pipe
		pipe.setTransparency(TransparencyAttrib.MDual)
		#R,G,B,A
		pipe.setColor(0.7, 0.7, 0, 0.5)
		pipe.setCollideMask(BitMask32.allOn())
		pipe.reparentTo(render)
		pipeObjectsList.append(pipe)
		return pipe

		#Loads any object if it's not a pipe
	def loadAnotherObject(self, namepath, position, scaleObject, R, G, B, A, rotX, rotY, rotZ):
		object = loader.loadModel(namepath)
		# Reparent the model to render.
		object.reparentTo(render)
		self.setObjectScale(object, scaleObject[0], scaleObject[1], scaleObject[2])
		self.setObjectPosition(object, position[0], position[1], position[2])
		
		if A < 1:
			object.setTransparency(TransparencyAttrib.MAlpha)
			object.setColor(R, G, B, A)
		else:
			object.setColor(R, G, B, 1)

		self.centerPivot(object)
		object.setHpr(rotX, rotY, rotZ)
		object.setCollideMask(BitMask32.allOn())
		return object

	def physicsON(self, gravity):
		global gravityFN
		global gravityFNP
		global gravityForce
		
		gravityFN = ForceNode('world-forces')
		gravityFNP = render.attachNewNode(gravityFN)
		gravityForce = LinearVectorForce(0,0,gravity) #gravity acceleration
		gravityFN.addForce(gravityForce)
		base.physicsMgr.addLinearForce(gravityForce)
		return


	def loadSphere(self):
		global sphere
		global PhysicsObject
		sphere = self.loadAnotherObject("Panda_models/ball", [-0.8, -0.65, 47], [0.025,0.025,0.025], 1, 0, 1, 1, 0, 0, 0)
		sphere.reparentTo(render)
		sphere.setCollideMask(BitMask32.allOff())

		self.Node = NodePath(PandaNode("PhysicsNode"))
		self.Node.reparentTo(render)
		self.an = ActorNode("sphere-physics")
		self.anp = self.Node.attachNewNode(self.an)
		self.anp.setPos(0, 0, 50)

		self.an.getPhysicsObject().setVelocity(0, 0, 0)

		self.collider = self.anp.attachNewNode(CollisionNode('projectilcnode'))
		self.collider.node().addSolid(CollisionSphere(0, 0, 0, 0.05))
		self.collider.node().setIntoCollideMask(BitMask32.allOff())

		self.an.getPhysicsObject().setMass(20)
		base.physicsMgr.attachPhysicalNode(self.an)
		PhysicsObject = self.an.getPhysicsObject()
		# Reparent the model to render.

		self.Node.reparentTo(render)
		sphere.reparentTo(self.anp)


		# Initialize the collision traverser.
		base.cTrav = CollisionTraverser()

		# Initialize the Pusher collision handler.

		self.pusher = PhysicsCollisionHandler()
		self.pusher.setHorizontal(False)
		self.pusher.setDynamicFrictionCoef(0.1)
		self.pusher.setStaticFrictionCoef(0.1)

		self.pusher.addCollider(self.collider, self.anp)
		base.cTrav.addCollider(self.collider, self.pusher)
		base.cTrav.setRespectPrevTransform(True)

		#self.collider.show()
		#base.cTrav.showCollisions(render)

		self.Node.reparentTo(render)

		return

	#Load a texture and attach it to some object
	def attachTexturetoObject(self, objectgiven, texturename):
		texture = loader.loadTexture("Textures/" + texturename)

		#objectgiven.setTexScale(TextureStage.getDefault(), 1, 1)
		objectgiven.setTexture(texture)
		return objectgiven

	#Scale an object
	def setObjectScale(self, objectgiven, x, y, z):
		scaledObject = objectgiven.setScale(x, y, z)
		return scaledObject

	#Set a new position for an object
	def setObjectPosition(self, objectgiven, x, y, z):
		newPlaceObject = objectgiven.setPos(x, y, z)
		return newPlaceObject

	#Activate the lights
	def lights(self):		
		global lightList
		global pipeObjectsList

		dlight = DirectionalLight('dlight')
		dlight.setColor(VBase4(0.8, 0.8, 1, 1))
		dlnp = render.attachNewNode(dlight)
		dlnp.setHpr(0, -180, 0)
		render.setLight(dlnp)
		lightList.append(dlnp)
		
		dlight2 = DirectionalLight('dlight')
		dlight2.setColor(VBase4(0.8, 0.8, 0.5, 1))
		dlnp2 = render.attachNewNode(dlight2)
		dlnp2.setHpr(0, 145, 0)		
		render.setLight(dlnp2)
		lightList.append(dlnp2)

	
#####PIPES#######################
# 'Pipe Name' - Pipes that may be used after 'Pipe Name'
#---
#MainPipe.egg makes Vertical, the Horizontals and Diagonals
#QuadrantTube.egg makes all the Quadrants
#BentTube.egg makes all the Bents
#---
#Vertical - Vertical, Quadrant 3, Quadrant 4, Bent 1, Bent 2
#Horizontal Left - Bent 6, Quadrant 2, Horizontal Left
#Horizontal Right - Bent 5, Quadrant 1, Horizontal Right
#Diagonal Right - Bent 3, Diagonal Right
#Diagonal Left - Bent 4, Diagonal Left
#Quadrant 1 - Vertical, Quadrant 3, Quadrant 4, Bent 1, Bent 2
#Quadrant 2 - Vertical, Quadrant 3, Quadrant 4, Bent 1, Bent 2
#Quadrant 3 - Horizontal Right, Bent 5, Quadrant 1
#Quadrant 4 - Horizontal Left, Bent 6, Quadrant 2
#Bent 1 - Diagonal Right, Bent 3
#Bent 2 - Diagonal Left, Bent 4
#Bent 3 - Vertical, Quadrant 3, Quadrant 4, Bent 1, Bent 2
#Bent 4 - Vertical, Quadrant 3, Quadrant 4, Bent 1, Bent 2
#Bent 5 - Diagonal Right, Bent 3
#Bent 6 - Diagonal Left, Bent 4


	#vertical pipe: |
	def vertical(self, x, xAdjust, y, z, zAdjust):
		global NextTubes
		global LastTube
		global randomPower
		global PhysicsObject
		global tubeNameSpecial
		
		z = z + zAdjust
		x = x + xAdjust
		TubesOnGame.append("Vertical")
		NextTubes = ["Vertical", "Quadrant3", "Quadrant4", "Bent1", "Bent2"]

		pipe = self.loadPipe("Panda_models/MainTube", x, y, z)
		pipe = self.centerPivot(pipe)

		if tubeNameSpecial == "VerticalVelocity" and PhysicsObject <> "":
			PhysicsObject.setVelocity(0,0,0)

		self.afterDrawingAdjustment(x, z)

		LastTube = pipe
		return pipe

	#Vertical pipe with rotation: 
	def diagonalRight(self, x, xAdjust, y, z, zAdjust):
		global NextTubes
		global LastTube
		global randomPower
		global PhysicsObject
		global tubeNameSpecial

		z = z + zAdjust
		x = x + xAdjust
		TubesOnGame.append("DiagonalRight")
		NextTubes = ["Bent3", "DiagonalRight"]

		pipe = self.loadPipe("Panda_models/MainTube", x, y, z)
		pipe = self.centerPivot(pipe)
		pipe.setHpr(0, 0, 45)

		if tubeNameSpecial == "DiagonalRightVelocity":
			PhysicsObject.setVelocity(0,0,0)

		self.afterDrawingAdjustment(x, z)

		LastTube = pipe
		return pipe

	#Vertical pipe with rotation:
	def diagonalLeft(self, x, xAdjust, y, z, zAdjust):
		global NextTubes
		global LastTube
		global randomPower
		global PhysicsObject
		global changes

		z = z + zAdjust
		x = x + xAdjust
		TubesOnGame.append("DiagonalLeft")
		NextTubes = ["Bent4", "DiagonalLeft"]

		pipe = self.loadPipe("Panda_models/MainTube", x, y, z)
		pipe = self.centerPivot(pipe)
		pipe.setHpr(0, 0, -45)

		self.afterDrawingAdjustment(x, z)

		LastTube = pipe
		return pipe

	#Vertical pipe with rotation. The end is to the right.
	def horizontalRight(self, x, xAdjust, y, z, zAdjust):
		global NextTubes
		global LastTube
		global randomPower
		global PhysicsObject

		z = z + zAdjust
		x = x + xAdjust
		TubesOnGame.append("HorizontalRight")
		NextTubes = ["Bent5", "Quadrant1", "HorizontalRight"]

		pipe = self.loadPipe("Panda_models/MainTube", x, y, z)
		pipe = self.centerPivot(pipe)
		pipe.setHpr(0, 0, 90)

		self.afterDrawingAdjustment(x, z)

		LastTube = pipe
		return pipe

	#Vertical pipe with rotation. The end is to the left.
	def horizontalLeft(self, x, xAdjust, y, z, zAdjust):
		global NextTubes
		global LastTube
		global randomPower
		global PhysicsObject

		z = z + zAdjust
		x = x + xAdjust
		TubesOnGame.append("HorizontalLeft")
		NextTubes = ["Bent6", "Quadrant2", "HorizontalLeft"]

		pipe = self.loadPipe("Panda_models/MainTube", x, y, z)
		pipe = self.centerPivot(pipe)
		pipe.setHpr(0, 0, 90)

		self.afterDrawingAdjustment(x, z)

		LastTube = pipe
		return pipe

	# 1\\4 of a circle. First quadrant.
	def Quadrant1(self, x, xAdjust, y, z, zAdjust):
		global NextTubes
		global LastTube
		global randomPower
		global PhysicsObject

		z = z + zAdjust
		x = x + xAdjust
		TubesOnGame.append("Quadrant1")
		NextTubes = ["Vertical", "Quadrant3", "Quadrant4", "Bent1", "Bent2"]

		pipe = self.loadPipe("Panda_models/QuadrantTube", x, y, z)
		pipe = self.centerPivot(pipe)
		pipe.setHpr(180, 0, 180)

		self.afterDrawingAdjustment(x, z)

		LastTube = pipe
		return pipe

	# 1\\4 of a circle. Second quadrant.
	def Quadrant2(self, x, xAdjust, y, z, zAdjust):
		global NextTubes
		global LastTube
		global randomPower
		global PhysicsObject
		global changes
		global tubeNameSpecial

		z = z + zAdjust
		x = x + xAdjust
		TubesOnGame.append("Quadrant2")
		NextTubes = ["Vertical", "Quadrant3", "Quadrant4", "Bent1", "Bent2"]
		pipe = self.loadPipe("Panda_models/QuadrantTube", x, y, z)
		pipe = self.centerPivot(pipe)
		pipe.setHpr(0, 0, 180)

		if tubeNameSpecial == "Quadrant2plus1change":
			changes = changes + 1
			self.threeChanges()
		if tubeNameSpecial == "Quadrant2plus3change":
			changes = changes + 3
			self.threeChanges()
		if tubeNameSpecial == "Quadrant2plus10change":
			changes = changes + 10
			self.threeChanges()

		self.afterDrawingAdjustment(x, z)

		LastTube = pipe
		return pipe

	# 1\\4 of a circle. Third quadrant.
	def Quadrant3(self, x, xAdjust, y, z, zAdjust):
		global NextTubes
		global LastTube
		global randomPower
		global PhysicsObject
		global points
		global tubeNameSpecial

		z = z + zAdjust
		x = x + xAdjust
		TubesOnGame.append("Quadrant3")
		NextTubes = ["HorizontalRight", "Quadrant1", "Bent5"]

		pipe = self.loadPipe("Panda_models/QuadrantTube", x, y, z)
		pipe = self.centerPivot(pipe)
		pipe.setHpr(180, 0, 0)

		if tubeNameSpecial == "Quadrant3plus5":
			points = str(int(points) + 5)
			self.points(1)
		if tubeNameSpecial == "Quadrant3plus10":
			points = str(int(points) + 10)
			self.points(1)
		if tubeNameSpecial == "Quadrant3plus18":
			points = str(int(points) + 18)
			self.points(1)
		if tubeNameSpecial == "Quadrant3plus200":
			points = str(int(points) + 200)
			self.points(1)


		self.afterDrawingAdjustment(x, z)

		LastTube = pipe
		return pipe

	# 1\\4 of a circle. Fourth quadrant.
	def Quadrant4(self, x, xAdjust, y, z, zAdjust):
		global NextTubes
		global LastTube
		global randomPower
		global PhysicsObject

		z = z + zAdjust
		x = x + xAdjust
		TubesOnGame.append("Quadrant4")
		NextTubes = ["HorizontalLeft", "Quadrant2", "Bent6"]

		pipe = self.loadPipe("Panda_models/QuadrantTube", x, y, z)
		pipe = self.centerPivot(pipe)

		self.afterDrawingAdjustment(x, z)
		LastTube = pipe
		return pipe

	# Bent pipes:


	def Bent1(self, x, xAdjust, y, z, zAdjust):
		global NextTubes
		global LastTube
		global randomPower
		global PhysicsObject

		z = z + zAdjust
		x = x + xAdjust
		TubesOnGame.append("Bent1")
		NextTubes = ["DiagonalRight", "Bent3"]

		pipe = self.loadPipe("Panda_models/BentTube", x, y, z)
		pipe = self.centerPivot(pipe)
		pipe.setHpr(180, 180, 0)

		self.afterDrawingAdjustment(x, z)

		LastTube = pipe
		return pipe

	def Bent2(self, x, xAdjust, y, z, zAdjust):
		global NextTubes
		global LastTube
		global randomPower
		global PhysicsObject
		global changes
		global tubeNameSpecial

		z = z + zAdjust
		x = x + xAdjust
		TubesOnGame.append("Bent2")
		NextTubes = ["DiagonalLeft", "Bent4"]

		pipe = self.loadPipe("Panda_models/BentTube", x, y, z)
		pipe = self.centerPivot(pipe)
		pipe.setHpr(0, 180, 0)

		if tubeNameSpecial == "Bent2plus1change":
			changes = changes + 1
			self.threeChanges()
		if tubeNameSpecial == "Bent2plus3change":
			changes = changes + 3
			self.threeChanges()
		if tubeNameSpecial == "Bent2plus10change":
			changes = changes + 10
			self.threeChanges()


		self.afterDrawingAdjustment(x, z)

		LastTube = pipe
		return pipe

	def Bent3(self, x, xAdjust, y, z, zAdjust):
		global NextTubes
		global LastTube
		global randomPower
		global PhysicsObject
		global points
		global tubeNameSpecial

		z = z + zAdjust
		x = x + xAdjust
		TubesOnGame.append("Bent3")
		NextTubes = ["Vertical", "Quadrant3", "Quadrant4", "Bent1", "Bent2"]

		pipe = self.loadPipe("Panda_models/BentTube", x, y, z)
		pipe = self.centerPivot(pipe)

		if tubeNameSpecial == "Bent3plus8":
			points = str(int(points) + 8)
			self.points(1)
		if tubeNameSpecial == "Bent3plus16":
			points = str(int(points) + 16)
			self.points(1)
		if tubeNameSpecial == "Bent3plus23":
			points = str(int(points) + 23)
			self.points(1)
		if tubeNameSpecial == "Bent3plus1000":
			points = str(int(points) + 1000)
			self.points(1)


		self.afterDrawingAdjustment(x, z)

		LastTube = pipe
		return pipe

	def Bent4(self, x, xAdjust, y, z, zAdjust):
		global NextTubes
		global LastTube
		global randomPower
		global PhysicsObject

		z = z + zAdjust
		x = x + xAdjust
		TubesOnGame.append("Bent4")
		NextTubes = ["Vertical", "Quadrant3", "Quadrant4", "Bent1", "Bent2"]

		pipe = self.loadPipe("Panda_models/BentTube", x, y, z)
		pipe = self.centerPivot(pipe)
		pipe.setHpr(180, 0, 0)

		self.afterDrawingAdjustment(x, z)

		LastTube = pipe
		return pipe

	def Bent5(self, x, xAdjust, y, z, zAdjust):
		global NextTubes
		global LastTube
		global randomPower
		global PhysicsObject

		z = z + zAdjust
		x = x + xAdjust
		TubesOnGame.append("Bent5")
		NextTubes = ["DiagonalRight", "Bent3"]

		pipe = self.loadPipe("Panda_models/BentTube", x, y, z)
		pipe = self.centerPivot(pipe)
		pipe.setHpr(180, 0, 90)

		self.afterDrawingAdjustment(x, z)
		LastTube = pipe
		return pipe


	def Bent6(self, x, xAdjust, y, z, zAdjust):
		global NextTubes
		global LastTube
		global randomPower
		global PhysicsObject

		z = z + zAdjust
		x = x + xAdjust
		TubesOnGame.append("Bent6")
		NextTubes = ["DiagonalLeft", "Bent4"]

		pipe = self.loadPipe("Panda_models/BentTube", x, y, z)
		pipe = self.centerPivot(pipe)
		pipe.setHpr(0, 0, 90)

		self.afterDrawingAdjustment(x, z)

		LastTube = pipe
		return pipe
######################## END OF PIPE FUNCTIONS ###################################################################

	#Used to the simplify the rotation.
	def centerPivot(self, NP):
		pivot = NP.getBounds().getCenter()
		parent = NP.getParent()
		# create the new parent node under the original parent
		newNP = parent.attachNewNode('objectNode')
		# bring the new parent to the center
		newNP.setPos(pivot)
		# and relocate the node without changing any of it's transformation
		NP.wrtReparentTo(newNP)
		return newNP


	#We did not find a way for the tubes to be placed after another following constant values. Maybe its due to inexperience.
	#That's why this function exists, to adjust the coordinates of each tube, depending on the one that came before.
	def adjustCoordinates(self, ChosenTubeVar):
		CoordList = []

		if TubesOnGame[len(TubesOnGame)-1] == "Vertical":
			if ChosenTubeVar == "Vertical":
				CoordList = [-0.01, 0, -4.6]
			if ChosenTubeVar == "Quadrant3":
				CoordList = [-2.08, 0, - 4.6]
			if ChosenTubeVar == "Quadrant4":
				CoordList = [0, 0, - 4.6]
			if ChosenTubeVar == "Bent1":
				CoordList = [-2.9, 0, - 3.5]
			if ChosenTubeVar == "Bent2":
				CoordList = [-0.6, 0, - 3.5]
		if TubesOnGame[len(TubesOnGame)-1] == "HorizontalLeft":
			if ChosenTubeVar == "Bent6":
				CoordList = [4.5, 0, 1.6]
			if ChosenTubeVar == "HorizontalLeft":
				CoordList = [4.6, 0, -0.02]
			if ChosenTubeVar == "Quadrant2":
				CoordList = [3.0, 0, -1.55]
		if TubesOnGame[len(TubesOnGame)-1] == "HorizontalRight":
			if ChosenTubeVar == "Bent5":
				CoordList = [-8.0, 0, 1.6]
			if ChosenTubeVar == "HorizontalRight":
				CoordList = [-4.6, 0, -0.02]
			if ChosenTubeVar == "Quadrant1":
				CoordList = [-5.1, 0, -1.6]
		if TubesOnGame[len(TubesOnGame)-1] == "DiagonalRight":
			if ChosenTubeVar == "Bent3":
				CoordList = [-4.8, 0, -2.33]
			if ChosenTubeVar == "DiagonalRight":
				CoordList = [-3.22, 0, -3.25]
		if TubesOnGame[len(TubesOnGame)-1] == "DiagonalLeft":
			if ChosenTubeVar == "Bent4":
				CoordList = [1.2, 0, -2.25]
			if ChosenTubeVar == "DiagonalLeft":
				CoordList = [3.1, 0, -3.1]
		if TubesOnGame[len(TubesOnGame)-1] == "Quadrant1":
			if ChosenTubeVar == "Vertical":
				CoordList = [0, 0, -3.7]
			if ChosenTubeVar == "Quadrant3":
				CoordList = [-2.1, 0, -3.7]
			if ChosenTubeVar == "Quadrant4":
				CoordList = [0, 0, -3.7]
			if ChosenTubeVar == "Bent1":
				CoordList = [-2.95, 0, -2.7]
			if ChosenTubeVar == "Bent2":
				CoordList = [-0.6, 0, -2.7]
		if TubesOnGame[len(TubesOnGame)-1] == "Quadrant2":
			if ChosenTubeVar == "Vertical":
				CoordList = [2.1, 0, -3.7]
			if ChosenTubeVar == "Quadrant3":
				CoordList = [0, 0, -3.7]
			if ChosenTubeVar == "Quadrant4":
				CoordList = [2.1, 0, -3.7]
			if ChosenTubeVar == "Bent1":
				CoordList = [-0.8, 0, -2.7]
			if ChosenTubeVar == "Bent2":
				CoordList = [1.5, 0, -2.7]
		if TubesOnGame[len(TubesOnGame)-1] == "Quadrant3":
			if ChosenTubeVar == "Bent5":
				CoordList = [-6.4, 0, 0.9]
			if ChosenTubeVar == "HorizontalRight":
				CoordList = [-3.0, 0, -0.75]
			if ChosenTubeVar == "Quadrant1":
				CoordList = [-3.6, 0, -2.25]
		if TubesOnGame[len(TubesOnGame)-1] == "Quadrant4":
			if ChosenTubeVar == "Bent6":
				CoordList = [5.1, 0, 0.85]
			if ChosenTubeVar == "HorizontalLeft":
				CoordList = [5.1, 0, -0.7]
			if ChosenTubeVar == "Quadrant2":
				CoordList = [3.6, 0, -2.25]
		if TubesOnGame[len(TubesOnGame)-1] == "Bent1":
			if ChosenTubeVar == "Bent3":
				CoordList = [-2.7, 0, -6.75]
			if ChosenTubeVar == "DiagonalRight":
				CoordList = [-1.3, 0, -7.8]
		if TubesOnGame[len(TubesOnGame)-1] == "Bent2":
			if ChosenTubeVar == "Bent4":
				CoordList = [2.7, 0, -6.75]
			if ChosenTubeVar == "DiagonalLeft":
				CoordList = [4.75, 0, -7.8]
		if TubesOnGame[len(TubesOnGame)-1] == "Bent3":
			if ChosenTubeVar == "Vertical":
				CoordList = [0.58, 0, -9.0]
			if ChosenTubeVar == "Quadrant3":
				CoordList = [-1.52, 0, -9.0]
			if ChosenTubeVar == "Quadrant4":
				CoordList = [0.55, 0, -9.0]
			if ChosenTubeVar == "Bent1":
				CoordList = [-2.3, 0, -8.0]
			if ChosenTubeVar == "Bent2":
				CoordList = [-0.02, 0, -8.1]
		if TubesOnGame[len(TubesOnGame)-1] == "Bent4":
			if ChosenTubeVar == "Vertical":
				CoordList = [2.95, 0, -9.0]
			if ChosenTubeVar == "Quadrant3":
				CoordList = [0.85, 0, -9.0]
			if ChosenTubeVar == "Quadrant4":
				CoordList = [2.95, 0, -9.0]
			if ChosenTubeVar == "Bent1":
				CoordList = [0.02, 0, -8.0]
			if ChosenTubeVar == "Bent2":
				CoordList = [2.3, 0, -8.0]
		if TubesOnGame[len(TubesOnGame)-1] == "Bent5":
			if ChosenTubeVar == "Bent3":
				CoordList = [-4.6, 0, -4.6]
			if ChosenTubeVar == "DiagonalRight":
				CoordList = [-3.2, 0, -5.7]
		if TubesOnGame[len(TubesOnGame)-1] == "Bent6":
			if ChosenTubeVar == "Bent4":
				CoordList = [4.6, 0, -4.6]
			if ChosenTubeVar == "DiagonalLeft":
				CoordList = [6.7, 0, -5.7]

		return CoordList

		#Function that loads the user points on the screen
	def loadScreenText(self, text, position, scale, mayChange, fg):
		textObject = OnscreenText(text=text, pos=(position[0], position[1]), scale=scale, mayChange=mayChange, fg=(fg[0], fg[1], fg[2], fg[3]))
		return textObject

		#Restart the game
	def restartGame(self):
		global gameOverTexts
		global pipeObjectsList
		global sphere
		global isItOver
		global points
		global PhysicsObject
		global userNameObjectLabel
		global buttonObjectList
		global buttonChange
		global TubesOnGame
		global GiantTube
		global music
		global CameraPosition
		global changes
		global pointText
		global PositionListZ
		global PositionListX
		global lightList
		global gravity
		global userName		

		
		for pipe in pipeObjectsList:
			pipe.removeNode()
		for button in buttonObjectList:
			button.destroy()
		for light in lightList:
			render.clearLight(light)
		for text in gameOverTexts:
			text.destroy()
		if music.status() == music.PLAYING:
			music.stop()
			
		
		sphere.removeNode()		
		GiantTube.removeNode()
		TubesOnGame = []
		PositionListX = []
		PositionListZ = []
		PhysicsObject = ""
		userName = ""
		CameraPosition = 20
		changes = 3
		isItOver = 0
		points = "0"
		pointText.destroy()
		userNameObjectLabel.destroy()
		buttonChange.destroy()
		taskMgr.remove("camera")
		base.accept("home", self.dummyFunction)
		base.accept("space", self.dummyFunction)
		base.accept("a", self.dummyFunction)
		base.accept("d", self.dummyFunction)		
		self.physicsON(-gravity[0])
		self.loadMenu()
		return

		#Add points to the player
	def points(self, value=0):
		global points
		global pointText
		global PositionListZ

		if pointText <> "":
			pointText.destroy()

		if len(PositionListZ) > 1:
			if value == 0:
				points = str(int(points) + 1)
			else:
				points = str(int(points))
			pointText = self.loadScreenText("Score: " + points, [0.9, 0.9], 0.07, 1, [1, 0, 0, 1])
		else:
			pointText = self.loadScreenText("Score: 0", [0.9, 0.9], 0.07, 1, [1, 0, 0, 1])
		return pointText

		#Load the buttons that the user uses to choose the tube to be drawn
	def loadButtonsAndLoadTube(self):
		global NextTubes
		global buttonObject
		global buttonObjectList
		global TubesOnGame
		global randomPower
		global tubeNameSpecial
		global gravity

		#The next two blocks of codes are used to test.

		#------Comment this if the code below is not commented------------------
#		global buttonChange
#
#		if buttonChange <> "":
#			buttonChange.destroy()
#		randomList = NextTubes
		#-----------------------------------------------------------------------
		

		#--------Comment this if the code above is not commented----------------
		randomList = [random.choice(NextTubes), random.choice(NextTubes)]

		while randomList[0] == randomList[1]:
			randomList[1] = random.choice(NextTubes)
		#-----------------------------------------------------------------------

		key = "a"
		randomPower = random.randint(1,1000)
		
		# wait until the user select the first tube
		if len(TubesOnGame) == 2:
			self.physicsON(gravity[0])

		buttonPos = [-0.2, 0.0, -0.9]
		for tube in randomList:
			if tube == "Vertical":
				commandFunction = self.vertical
				tubeName = "Vertical"
			if tube == "Quadrant1":
				commandFunction = self.Quadrant1
				tubeName = "Quadrant1"
			if tube == "Quadrant2":
				commandFunction = self.Quadrant2
				tubeName = "Quadrant2"
			if tube == "Quadrant3":
				commandFunction = self.Quadrant3
				tubeName = "Quadrant3"
			if tube == "Quadrant4":
				commandFunction = self.Quadrant4
				tubeName = "Quadrant4"
			if tube == "HorizontalRight":
				commandFunction = self.horizontalRight
				tubeName = "HorizontalRight"
			if tube == "HorizontalLeft":
				commandFunction = self.horizontalLeft
				tubeName = "HorizontalLeft"
			if tube == "DiagonalLeft":
				commandFunction = self.diagonalLeft
				tubeName = "DiagonalLeft"
			if tube == "DiagonalRight":
				commandFunction = self.diagonalRight
				tubeName = "DiagonalRight"
			if tube == "Bent1":
				commandFunction = self.Bent1
				tubeName = "Bent1"
			if tube == "Bent2":
				commandFunction = self.Bent2
				tubeName = "Bent2"
			if tube == "Bent3":
				commandFunction = self.Bent3
				tubeName = "Bent3"
			if tube == "Bent4":
				commandFunction = self.Bent4
				tubeName = "Bent4"
			if tube == "Bent5":
				commandFunction = self.Bent5
				tubeName = "Bent5"
			if tube == "Bent6":
				commandFunction = self.Bent6
				tubeName = "Bent6"
			#print tube
			#print randomPower
			power = self.verifyPowers(tube, randomPower)
			if power <> 0:
				tubeNameSpecial = power[0]				
				commandFunction = power[1]
				fileName = tubeNameSpecial
			if power == 0:
				fileName = tubeName				
						
			CoordList = self.adjustCoordinates(tube)
			buttonObject = DirectButton(image="Button_images/" + fileName + ".jpg", scale=.09, pressEffect=1, command=commandFunction, extraArgs=(PositionListX[len(PositionListX)-1], CoordList[0], 0, PositionListZ[len(PositionListZ)-1], CoordList[2]))
			buttonObject.setPos(buttonPos[0], buttonPos[1], buttonPos[2])
			buttonPos[0] = buttonPos[0] + 0.4
			base.accept(key, commandFunction, [PositionListX[len(PositionListX)-1], CoordList[0], 0, PositionListZ[len(PositionListZ)-1], CoordList[2]])
			buttonObjectList.append(buttonObject)
			key = "d"
		randomList = []

		return

	def verifyPowers(self, tube, RP):
		if tube == "Bent3":
			#+8
			if RP > 10 and RP < 300:
					return ["Bent3plus8", self.Bent3]
			#+16
			if RP > 300 and RP < 500:
					return ["Bent3plus16", self.Bent3]
			#+23
			if RP > 700 and RP < 800:
					return ["Bent3plus23", self.Bent3]
			#+1000
			if RP == 1000:
					return ["Bent3plus1000", self.Bent3]
			else:
				return 0
		elif tube == "Bent2":
			#+1 change
			if RP > 10 and RP < 200:
				return ["Bent2plus1change", self.Bent2]
			#+3 change
			if RP > 200 and RP < 300:
				return ["Bent2plus3change", self.Bent2]
			#+10 change
			if RP > 300 and RP < 302:
				return ["Bent2plus10change", self.Bent2]
			else:
				return 0
		elif tube == "Quadrant3":
			#+5
			if RP > 10 and RP < 300:
				return ["Quadrant3plus5", self.Quadrant3]
			#+10
			if RP > 300 and RP < 500:
				return ["Quadrant3plus10", self.Quadrant3]
			#+18
			if RP > 500 and RP < 600:
				return ["Quadrant3plus18", self.Quadrant3]
			#+200
			if RP > 600 and RP < 602:
				return ["Quadrant3plus200", self.Quadrant3]
			else:
				return 0
		elif tube == "Quadrant2":
			#+1 change
			if RP > 10 and RP < 200:
				return ["Quadrant2plus1change", self.Quadrant2]
			#+3 change
			if RP > 445 and RP < 545:
				return ["Quadrant2plus3change", self.Quadrant2]
			#+10 change
			if RP > 300 and RP < 302:
				return ["Quadrant2plus10change", self.Quadrant2]
			else:
				return 0
		elif tube == "DiagonalRight":
			#velocity = 0
			if RP > 10 and RP < 200:
				return ["DiagonalRightVelocity", self.diagonalRight]
			else:
				return 0
		elif tube == "Vertical":
			#velocity = 0
			if RP > 500 and RP < 650:
				return ["VerticalVelocity", self.vertical]
			else:
				return 0
		else:
			return 0

	#Adds positions to lists, destroy the buttons that won't be used, add points to the player and call the button function again.
	def afterDrawingAdjustment(self, PositionX, PositionZ):
		global buttonObjectList
		PositionListX.append(PositionX)
		PositionListZ.append(PositionZ)
		for button in buttonObjectList:
			button.destroy()

		buttonObjectList = []
		self.points()
		self.loadButtonsAndLoadTube()

		#Verifies if the game reached the conditions for the player to lose.
	def isGameOver(self):
		global LastTube
		global PhysicsObject
		global points
		global TubesOnGame
		global buttonChange
		global gameOverTexts

		if LastTube <> "" and PhysicsObject <> "":
			if (PhysicsObject.getPosition().getZ() < LastTube.getZ()-10) or (PhysicsObject.getPosition().getX() > 21) or (PhysicsObject.getPosition().getX() < -21):
				gameOverTexts.append(self.loadScreenText("GAME OVER!", [0,0,0], 0.2, 1, [1, 0, 0, 1]))
				gameOverTexts.append(self.loadScreenText("You won " + points + " points and used " + str(len(TubesOnGame)) + " tubes." , [0,-0.5,0], 0.08, 1, [1, 0, 0, 1]))
				for button in buttonObjectList:
					button.destroy()
					if buttonChange <> "":
						buttonChange.destroy()
				base.accept("space",self.dummyFunction)
				base.accept("a",self.dummyFunction)
				base.accept("d",self.dummyFunction)
				self.playMusic()
				gameoversong = base.loader.loadSfx("Music/fail.mp3")
				gameoversong.play()
				self.saveScore()
				return 1 #Game over
			else:
				return 0

		
	#Used to prevent the player to continue playing (with the keys) after the game is over.
	def dummyFunction(self):
		return 0

	#Game camera
	def camera(self, task):
		global CameraPosition
		global LastTube
		global isItOver
		global TubesOnGame
		global GiantTube
		global PhysicsObject

		base.disableMouse()		
		if isItOver == 0:
			isItOver = self.isGameOver()

		#If higher, the camera will descend faster.
		camVelocity = 0.08	

		point = self.map3dToAspect2d(render, LastTube.getPos())

		#print PhysicsObject.getVelocity()
		#print PhysicsObject.getTerminalVelocity()

		if point <> None:
			pointZ = point.getZ()			
			#Verifies if the camera must stop or continue
			if pointZ < 0.2 and pointZ > -0.8:				    
					CameraPosition = CameraPosition - camVelocity
					camera.setPos(0, 80, CameraPosition)
					camera.lookAt(0, 0, CameraPosition + 6)
					GiantTube.setZ(GiantTube.getZ() - camVelocity)					
			elif pointZ < -0.8:					
					CameraPosition = CameraPosition - (camVelocity + 0.52)
					camera.setPos(0, 80, CameraPosition)
					camera.lookAt(0, 0, CameraPosition + 6)
					GiantTube.setZ(GiantTube.getZ() - (camVelocity + 0.52))					

		elif point == None and len(TubesOnGame) > 1:
			CameraPosition = CameraPosition - (camVelocity + 0.52)
			camera.setPos(0, 80, CameraPosition)
			camera.lookAt(0, 0, CameraPosition + 6)
			GiantTube.setZ(GiantTube.getZ() - (camVelocity + 0.52))

		else:
			camera.setPos(0, 80, CameraPosition)
			camera.lookAt(0, 0, CameraPosition + 6)

		return Task.cont


	# it converts between objects on the screen and their 3D location for comparasion.
	def map3dToAspect2d(self, node, point):

		# Convert the point to the 3-d space of the camera
		p3 = base.cam.getRelativePoint(node, point)

		# Convert it through the lens to render2d coordinates
		p2 = Point2()
		if not base.camLens.project(p3, p2):
			return None

		r2d = Point3(p2[0], 0, p2[1])

		# And then convert it to aspect2d coordinates
		a2d = aspect2d.getRelativePoint(render2d, r2d)

		return a2d

		#Saves the user score
	def saveScore(self):
		global points
		global userName

		try:
			f = open("score.txt", "a")
			try:
					f.write(points+"-"+userName+"-")
			finally:
					f.close()
		except IOError:
				pass

	#Shows the highest scores
	def showLastscores(self):
		global frame
		global scoreScreenList
		global userName
		global difficultButtons
		global mainButtons

		for button in mainButtons:
			button.destroy()

		
		if frame <> "":
			frame.destroy()
		if userNameObjectLabel <> "":
			userNameObjectLabel.destroy()
		for buttons in difficultButtons:
			buttons.destroy()

		try:
			f = open("score.txt", "r")

			try:
				scoreScreenList.append(self.loadScreenText("Last scores", [0, 0.9], 0.07, 1, [1, 1, 0, 1]))
				scoreString = f.read()
				scores = scoreString.split("-")
				scores.remove("")
				scores.reverse()
				i = 0
				Z = 0.8
				if scoreString <> "":
					for score in scores:
						if i >= len(scores):
							break
						else:
							scoreScreenList.append(self.loadScreenText(scores[i] + " : " + scores[i+1], [0, Z], 0.07, 1, [1, 0, 0, 1]))
							i = i+2
							Z = Z-0.1
							if i > 15:
								break
				scoreScreenList.append(self.loadScreenText("Press Backspace to back", [0, Z-0.1], 0.07, 1, [1, 1, 0, 1]))
				base.accept("backspace", self.loadMenu)

			finally:
				f.close()
		except IOError:
				pass

	def loadMenu(self):			
			global frame			
			global scoreScreenList
			global helpTextList
			global gravity
			global difficultButtons
			global mainButtons
						
			base.accept("backspace", self.dummyFunction)

			for element in scoreScreenList:
				element.destroy()

			for element in helpTextList:
				element.destroy()
                        
			base.setBackgroundColor(0.4, 0.4, 0.4, 1)
			frame = DirectFrame(frameColor=(1, 1, 1, 1), frameSize=(-1, 1, -1, 1),  frameTexture="Textures/pipes.jpg")

			mainButtons = [
				DirectButton(text="Play!", text_fg=(0.5,0.5,0.5,1), scale=.09, pressEffect=1, command=self.preInit, pos = (0, 0.0, 0.2), state = DGG.DISABLED ),
				DirectButton(text="Show Last Scores", scale=.09, pressEffect=1, command=self.showLastscores, pos = (0, 0.0 ,0.0)),
				DirectButton(text="Help", scale=.09, pressEffect=1, command = self.callHelp,  pos = (0, 0.0, -0.2)),
				DirectButton(text="Exit", scale=.09, pressEffect=1, command= exit,  pos = (0, 0.0, -0.4)),
				DirectEntry(text = userName ,scale=.1, initialText="Enter your name here", numLines = 1,focus=0, focusInCommand=self.clearEntryText, pos=(-0.4, 0.0, 0.4), command = self.saveUser)
            ]

			difficultButtons = [
				DirectRadioButton(text = "Easy", variable= gravity, value=[-2], scale=.09, pos=(-0.4,0,-0.7), indicatorValue = 0),
				DirectRadioButton(text = "Normal", variable= gravity, value=[-5], scale=.09, pos=(0.1,0,-0.7), indicatorValue = 0),
				DirectRadioButton(text = "Hard", variable= gravity, value=[-10], scale=.09, pos=(0.6,0,-0.7), indicatorValue = 0) ]
			for button in difficultButtons:
				button.setOthers(difficultButtons)
                        
	def callHelp(self):
		global mainButtons
		global frame
		global helpTextList
		global difficultButtons

		for button in mainButtons:
			button.destroy()
		if frame <> "":
			frame.destroy()	
		if userNameObjectLabel <> "":
			userNameObjectLabel.destroy()
		for buttons in difficultButtons:
			buttons.destroy()


		helpTextList.append(self.loadScreenText("Help", [0, 0.9], 0.07, 1, [1, 1, 0, 1]))
		helpTextList.append(self.loadScreenText("Use the keys A and D to place the tubes. \n There are also two buttons with the same function as the keys. \n \n You also have 3 initial chances to change the loaded buttons. \
		\n Press SPACE or the button Change. \n \n There are special tubes: \n Points: Tubes that grant you free points, adding to the 1 standard point to each tube \n Changes: Tubes that grant you new chances to use the CHANGE button \n  \
		Stop Ball: Tubes that stop the ball to help you... or not... \n If you wish to restart the game, press HOME \n \n Go on! Keep the ball on the tubes!", [0, 0.8], 0.07, 1, [0, 1, 0, 1]))
		helpTextList.append(self.loadScreenText("Press Backspace to back", [0, -0.3], 0.07, 1, [1, 1, 0, 1]))
		base.accept("backspace", self.loadMenu)

	#Just clear the text entry for the user name
	def clearEntryText(self):		   
		   global mainButtons
		   mainButtons[4].enterText('')

	#Save the user name to use in the score
	def saveUser(self, userNameVar):
		global userNameObjectLabel
		global userName
		global mainButtons	

		if userNameVar == "":
			userNameVar = "NO NAME TYPED"
		userNameObjectLabel = DirectLabel(text="Player: " + userNameVar,scale=.1,pos=(0.0,0,0.4), text_bg=(0,0,0,0))
		userName = userNameVar
		#Play
		mainButtons[0]["state"] = DGG.NORMAL	
		mainButtons[0]["text_fg"] = (0,0,0,1)
		#Last Scores
		mainButtons[1]["text_fg"]= (0.5,0.5,0.5,1)
		mainButtons[1]["state"] = DGG.DISABLED
		#Help
		mainButtons[2]["text_fg"] = (0.5,0.5,0.5,1)
		mainButtons[2]["state"] = DGG.DISABLED
		base.accept("b", self.preInit)		
		mainButtons[4].destroy()

	#Function that gives the player three chances to change the buttons
	def threeChanges(self):
		global changes
		global buttonChange
		if buttonChange <> "":
			buttonChange.destroy()

		base.accept("space", self.verifyButtonChange)
		buttonChange = DirectButton(text="Changes: " + str(changes), text_fg=(0,0,0,1), scale=.09, pressEffect=1, command=self.verifyButtonChange, pos = (0.7, 0.0, -0.9))

	#Deals with the CHANGE button
	def verifyButtonChange(self):
		global changes
		global buttonChange

		if changes > 0:
			changes = changes - 1
			self.threeChanges()
			self.loadButtonsAndLoadTube()
		if changes == 0 and buttonChange <> "":
			buttonChange["state"] = DGG.DISABLED
			buttonChange["text_fg"] = (0.5, 0.5, 0.5, 1)


	#Destroy the menu
	def preInit(self):	
		global frame		
		global userNameObjectLabel
		global difficultButtons
		global mainButtons

		for button in mainButtons:
			button.destroy()
		if frame <> "":
			frame.destroy()		
		if userNameObjectLabel <> "":
			userNameObjectLabel.destroy()
		for buttons in difficultButtons:
			buttons.destroy()

		self.initGame()

	# Play or stop the main song
	def playMusic(self):
		global music

		music.setLoop(True)
		if music.status() == music.READY:			
			music.play()
		elif music.status() == music.PLAYING:
			music.stop()


	#Draws the initial state on the screen
	def initGame(self):
		global ChosenTube
		global TubesOnGame		
		global GiantTube
		global scaleGiantTube
		global music

		base.accept("home", self.restartGame )
		base.setBackgroundColor(0, 0, 0, 1)
		base.enableParticles()
		#First tube on the game, a vertical one on this case
		self.vertical(0, 0, 0, FirstTubePos, 0)
		
		#play the music
		music = base.loader.loadSfx("Music/pipus.mp3")
		self.playMusic()
		base.accept("m", self.playMusic)

		#Turn on the lights
		self.lights()
		self.loadSphere()
		#Gives the player three initial chances to change the buttons.
		self.threeChanges()
		#Load the camera
		taskMgr.add(self.camera, "camera")
		#Load the GiantTube
		GiantTube = self.loadAnotherObject("Panda_models/GiantTube", [0, 10, 0], scaleGiantTube, 0, 0, 1, 1, 180, 0, 0)

		#self.attachTexturetoObject(GiantTube[2], "clouds.jpg")


		
		#base.oobe()

		return
